#!/usr/bin/env python3

import hashlib
import subprocess
from os import listdir
import os.path
from sys import exit
import gzip
import random

# Set the default directories:
temp_dir = os.path.join('.', 'temp')
fqtools_exec = os.path.join('..', '..', 'bin', 'fqtools')
fqrandom_exec = os.path.join('.', 'random-fastq')
alt_exec = os.path.join('.', 'process-fastq')

n_tests = 10000
all_passed = True
break_on_fail = True

reference_filename = os.path.join(temp_dir, 'reference.fastq')
test_filename = os.path.join(temp_dir, 'test.out')
alt_filename = os.path.join(temp_dir, 'alt.out')
reference_command = '{} -n1000 -bATGCN -qsanger -l0 -u100 -f{}'.format(fqrandom_exec, reference_filename)

commands = {
    'view': {
        'test':'{} -fF -FF view {} > {}'.format(fqtools_exec, reference_filename, test_filename),
        'alt':'{} view {} > {}'.format(alt_exec, reference_filename, alt_filename)
    },
    'head': {
        'test':'{} -fF -FF head -n{{}} {} > {}'.format(fqtools_exec, reference_filename, test_filename),
        'alt':'head -{{}} {} > {}'.format(reference_filename, alt_filename)
    },
    'count': {
        'test':'{} -fF count {} > {}'.format(fqtools_exec, reference_filename, test_filename),
        'alt':'echo "`cat {} | wc -l` / 4" | bc > {}'.format(reference_filename, alt_filename)
    },
    'header': {
        'test':'{} -fF header {} > {}'.format(fqtools_exec, reference_filename, test_filename),
        'alt':'{} header {} > {}'.format(alt_exec, reference_filename, alt_filename)
    },
    'header2': {
        'test':'{} -fF header2 {} > {}'.format(fqtools_exec, reference_filename, test_filename),
        'alt':'{} header2 {} > {}'.format(alt_exec, reference_filename, alt_filename)
    },
    'sequence': {
        'test':'{} -fF sequence {} > {}'.format(fqtools_exec, reference_filename, test_filename),
        'alt':'{} sequence {} > {}'.format(alt_exec, reference_filename, alt_filename)
    },
    'quality': {
        'test':'{} -fF quality {} > {}'.format(fqtools_exec, reference_filename, test_filename),
        'alt':'{} quality {} > {}'.format(alt_exec, reference_filename, alt_filename)
    },
    'fasta': {
        'test':'{} -fF fasta {} > {}'.format(fqtools_exec, reference_filename, test_filename),
        'alt':'{} fasta {} > {}'.format(alt_exec, reference_filename, alt_filename)
    },
    'basetab': {
        'test':'{} -dramul -fF basetab -a {} > {}'.format(fqtools_exec, reference_filename, test_filename),
        'alt':'{} basetab {} > {}'.format(alt_exec, reference_filename, alt_filename)
    },
    'qualtab': {
        'test':'{} -fF qualtab {} > {}'.format(fqtools_exec, reference_filename, test_filename),
        'alt':'{} qualtab {} > {}'.format(alt_exec, reference_filename, alt_filename)
    },
    'lengthtab': {
        'test':'{} -fF lengthtab {} > {}'.format(fqtools_exec, reference_filename, test_filename),
        'alt':'{} lengthtab {} > {}'.format(alt_exec, reference_filename, alt_filename)
    }
}

def runCommand(command): return subprocess.check_output(args=command, stdin=None, stderr=subprocess.STDOUT, shell=True, universal_newlines=True)

def fileMD5(filename):
    if '.gz' in filename: return hashlib.md5(gzip.open(filename,'rb').read()).hexdigest()
    return hashlib.md5(open(filename,'rb').read()).hexdigest()

iteration_str = '[{{:{0}}}/{{:{0}}}]'.format(len(str(n_tests)))
for test in range(n_tests):
    iteration = iteration_str.format(test + 1, n_tests)
    runCommand(reference_command)
    reference_md5 = fileMD5(reference_filename)
    for command in commands.keys():
        test_command = commands[command]['test']
        alt_command = commands[command]['alt']
        #Preprocess if necessary:
        if command == 'head':
            head_n = random.choice(range(1, 990))
            test_command = test_command.format(head_n)
            alt_command = alt_command.format(head_n * 4)
        runCommand(test_command)
        runCommand(alt_command)
        if fileMD5(test_filename) != fileMD5(alt_filename): result = 'FAILED'
        else: result = 'PASSED'
        print('{}: command "{}" {}'.format(iteration, command, result))
        if result == 'FAILED':
            print('{}: command "{}" reference file "{}" checksum is {}'.format(iteration, command, reference_filename, reference_md5))
            print('{}: command "{}" test file "{}" checksum is {}'.format(iteration, command, test_filename, fileMD5(test_filename)))
            print('{}: command "{}" alt file "{}" checksum is {}'.format(iteration, command, alt_filename, fileMD5(alt_filename)))
            print('{}: command "{}" test command is: {}'.format(iteration, command, test_command))
            print('{}: command "{}" alt command is: {}'.format(iteration, command, alt_command))
            all_passed = False
            if break_on_fail == True: exit('FAILED')

if all_passed == True: print('{} iterations passed'.format(n_tests))
    